﻿using RuoYi.Framework.Dto;
using RuoYi.Framework.Entity;
using System.Linq.Expressions;

namespace RuoYi.Framework.Repository;

/// <summary>
/// Repository interface
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public interface IRepository<TEntity> : IRepository where TEntity : class, IEntity
{
    #region Create(C)

    /// <summary>
    /// Inserts a new entity.
    /// </summary>
    /// <param name="entity"></param>
    /// <returns></returns>
    TEntity Insert(TEntity entity);

    /// <summary>
    /// Inserts a new entity.
    /// </summary>
    /// <param name="entity"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<TEntity> InsertAsync(TEntity entity, CancellationToken cancellationToken = default);

    /// <summary>
    /// Inserts multiple new entities.
    /// </summary>
    /// <param name="entities"></param>
    /// <returns></returns>
    bool Insert(IEnumerable<TEntity> entities);

    /// <summary>
    /// Inserts multiple new entities.
    /// </summary>
    /// <param name="entities"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<bool> InsertAsync(IEnumerable<TEntity> entities, CancellationToken cancellationToken = default);

    #endregion

    #region Read(R)

    /// <summary>
    /// Get a single entity by the given predicate.
    /// </summary>
    /// <param name="predicate"></param>
    /// <returns></returns>
    TEntity Get(Expression<Func<TEntity, bool>> predicate);

    /// <summary>
    /// Get a single entity by the given predicate.
    /// </summary>
    /// <param name="predicate"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);

    /// <summary>
    /// Gets a list of entities by the given predicate.
    /// </summary>
    /// <param name="predicate"></param>
    /// <returns></returns>
    List<TEntity> GetList(Expression<Func<TEntity, bool>> predicate);

    /// <summary>
    /// Gets a list of entities by the given predicate.
    /// </summary>
    /// <param name="predicate"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);

    /// <summary>
    /// Gets paged list of entities by the given predicate.
    /// </summary>
    /// <param name="pagingInput"></param>
    /// <param name="whereExpression"></param>
    /// <param name="orderByExpression"></param>
    /// <returns></returns>
    PagingOutputDto<TEntity> GetPaging(PagingInputDto pagingInput, Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>>? orderByExpression = null);

    /// <summary>
    /// Gets paged list of entities by the given predicate.
    /// </summary>
    /// <param name="pagingInput"></param>
    /// <param name="whereExpression"></param>
    /// <param name="orderByExpression"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<PagingOutputDto<TEntity>> GetPagingAsync(PagingInputDto pagingInput, Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>>? orderByExpression = null, CancellationToken cancellationToken = default);

    /// <summary>
    /// Gets total count of entities by the given predicate.
    /// </summary>
    /// <param name="predicate"></param>
    /// <returns></returns>
    long GetCount(Expression<Func<TEntity, bool>> predicate);

    /// <summary>
    /// Gets total count of entities by the given predicate.
    /// </summary>
    /// <param name="predicate"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<long> GetCountAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);

    #endregion

    #region Update(U)

    /// <summary>
    /// Updates an existing entity.
    /// </summary>
    /// <param name="entity"></param>
    /// <returns></returns>
    TEntity Update(TEntity entity);

    /// <summary>
    /// Updates an existing entity.
    /// </summary>
    /// <param name="entity"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<TEntity> UpdateAsync(TEntity entity, CancellationToken cancellationToken = default);

    /// <summary>
    /// Updates multiple entities.
    /// </summary>
    /// <param name="entities"></param>
    /// <returns></returns>
    bool Update(IEnumerable<TEntity> entities);

    /// <summary>
    /// Updates multiple entities.
    /// </summary>
    /// <param name="entities"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<bool> UpdateAsync(IEnumerable<TEntity> entities, CancellationToken cancellationToken = default);

    #endregion

    #region Delete(D)

    /// <summary>
    /// Deletes an entity.
    /// </summary>
    /// <param name="entity"></param>
    /// <returns></returns>
    bool Delete(TEntity entity);

    /// <summary>
    /// Deletes an entity.
    /// </summary>
    /// <param name="entity"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<bool> DeleteAsync(TEntity entity, CancellationToken cancellationToken = default);

    /// <summary>
    /// Deletes multiple entities.
    /// </summary>
    /// <param name="entities"></param>
    /// <returns></returns>
    bool Delete(IEnumerable<TEntity> entities);

    /// <summary>
    /// Deletes multiple entities.
    /// </summary>
    /// <param name="entities"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<bool> DeleteAsync(IEnumerable<TEntity> entities, CancellationToken cancellationToken = default);

    /// <summary>
    /// Deletes many entities by the given predicate.
    /// </summary>
    /// <param name="predicate"></param>
    /// <returns></returns>
    bool Delete(Expression<Func<TEntity, bool>> predicate);

    /// <summary>
    /// Deletes many entities by the given predicate.
    /// </summary>
    /// <param name="predicate"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<bool> DeleteAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);


    #endregion

}